package com.sun.umbrella.service.shiro.session;

import com.sun.umbrella.manager.utils.SerializableUtil;
import com.sun.umbrella.service.shiro.Constants;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.ValidatingSession;
import org.apache.shiro.session.mgt.eis.CachingSessionDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.StringUtils;

import java.io.Serializable;
import java.util.concurrent.TimeUnit;

/**
 * @author Jay
 * @version v1.0
 * @description session持久化
 * @date 2017-12-02 01:45
 */
public class ServerSessionDAO extends CachingSessionDAO {


    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    /**
     * 缓存有效期为2天
     */
    private final static Long TWO_DAYS = 2L;

    @Override
    public Serializable doCreate(Session session) {
        Serializable sessionId = generateSessionId(session);
        assignSessionId(session, sessionId);
        // 存session信息存2天
        redisTemplate.opsForValue().set(this.getHostKey(session.getHost()), sessionId.toString(), TWO_DAYS, TimeUnit.DAYS);
        redisTemplate.opsForValue().set(this.getSeesionIdKey(sessionId.toString()), SerializableUtil.serialize(session), TWO_DAYS, TimeUnit.DAYS);
        return sessionId;
    }

    @Override
    public void doUpdate(Session session) {
        // 如果会话过期或者停止了则没必要再更新
        if (session instanceof ValidatingSession && !((ValidatingSession) session).isValid()) {
            return;
        }
        String sessionStr = redisTemplate.opsForValue().get(this.getSeesionIdKey(session.getId().toString()));
        if (StringUtils.isEmpty(sessionStr)) {
            return;
        }
        // 存session信息存2天
        redisTemplate.opsForValue().set(this.getSeesionIdKey(session.getId().toString()), SerializableUtil.serialize(session), TWO_DAYS, TimeUnit.DAYS);
        redisTemplate.expire(this.getHostKey(session.getHost()), TWO_DAYS, TimeUnit.DAYS);
    }

    @Override
    public void doDelete(Session session) {
        String sessionStr = redisTemplate.opsForValue().get(this.getSeesionIdKey(session.getId().toString()));
        if (StringUtils.isEmpty(sessionStr)) {
            return;
        }
        redisTemplate.delete(this.getSeesionIdKey(session.getId().toString()));
    }

    @Override
    public Session doReadSession(Serializable sessionId) {
        String sessionStr = redisTemplate.opsForValue().get(this.getSeesionIdKey(sessionId.toString()));
        if (sessionStr == null) {
            return null;
        }
        return SerializableUtil.deserialize(sessionStr);
    }


    private String getHostKey(String key) {
        return new StringBuilder(Constants.SESSION_HOST_KEY)
                .append(key)
                .toString();
    }

    private String getSeesionIdKey(String key) {
        return new StringBuilder(Constants.SESSION_ID_KEY)
                .append(key)
                .toString();
    }
}

